
// ===============================================================================================================
// -*- C++ -*-
//
// ShaderProgram.hpp - GPU shader program interface.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __SHADER_PROGRAM_HPP__
#define __SHADER_PROGRAM_HPP__

// C++ std includes
#include <vector>

// Local includes
#include <Common.hpp>
#include <RefPtr.hpp>
#include <ReferenceCountable.hpp>

///
/// Interface for a GPU shader program.
/// Supported types are the Fragment Shader (Pixel Shader)
/// and the Vertex Shader, currently implemented for the OpenGL rendering API.
/// Shader info logs are redirected to the framework Log system by default.
///
class ShaderProgram : public ReferenceCountable {

public:

	// Public Interface:

	/// Creates a new shader program from the specified source files.
	/// The shader type (i.e: Vertex/Fragment shader) is detected by checking the source file extension,
	/// which must be either ".vert" for vertex shaders or ".frag" for fragment shaders.
	static ShaderProgram * Create(const std::string * srcFiles, size_t numFiles);

	/// Enable the shader program.
	void Enable(void) const;

	/// Disable the shader program (return to fixed functionality).
	void Disable(void) const;

	// TODO: Add get/set methods for the different shader data types !!!

	/// Set a shader uniform variable.
	void SetUniform1i(const char * name, int i);

	/// Set a shader uniform variable.
	void SetUniform1f(const char * name, float f);

	/// Set a shader uniform vector[4].
	void SetUniform4f(const char * name, float vec[4]);

	// ReferenceCountable Methods:

	virtual unsigned long AddRef(void) const;
	virtual unsigned long Release(void) const;
	virtual unsigned long ReferenceCount(void) const;

protected:

	virtual ~ShaderProgram(void);

private:

	// This will prevent the class from being staticaly allocated.
	// The only way to create an instance of it now is thru the ShaderProgram::Create() method.
	ShaderProgram(const std::string * srcFiles, size_t numFiles);

	// Disable copy.
	ShaderProgram(const ShaderProgram &);
	ShaderProgram & operator = (const ShaderProgram &);

	// Write the program info log to the default log output.
	void WriteInfoLog(void) const;

private:

	// Private Data:

	GLuint programObj; ///< Shader program object for OpenGL
	std::vector<GLuint> shaders; ///< Vertex & Fragment shader instances in this shader program
};

#endif // __SHADER_PROGRAM_HPP__